package vip.xiaonuo.modular.attendancerecord.service;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service;
import vip.xiaonuo.core.exception.ServiceException;
import vip.xiaonuo.facedoor.modular.memberuser.entity.MemberUser;
import vip.xiaonuo.facedoor.modular.memberuser.service.MemberUserService;
import vip.xiaonuo.modular.attendancedayset.entity.AttendanceDaySet;
import vip.xiaonuo.modular.attendancedayset.mapper.AttendanceDaySetMapper;
import vip.xiaonuo.modular.attendancegroup.entity.AttendanceGroup;
import vip.xiaonuo.modular.attendancerecord.entity.AttendanceRecord;
import vip.xiaonuo.modular.attendancerecord.mapper.AttendanceRecordMapper;
import vip.xiaonuo.modular.attendancerecord.param.AttendanceRecordParam;
import vip.xiaonuo.modular.attendanceshift.entity.AttendanceShift;
import vip.xiaonuo.modular.attendanceshift.service.AttendanceShiftService;
import vip.xiaonuo.modular.attendanceshiftgroup.entity.AttendanceShiftGroup;
import vip.xiaonuo.modular.attendanceshiftgroup.service.AttendanceShiftGroupService;
import vip.xiaonuo.redis.DayInfoService;

import javax.annotation.Resource;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;
import java.util.List;

@Service
public class AttendancePlanBaseService {

    protected SimpleDateFormat sdf_ym = new SimpleDateFormat("yyyyMM");

    protected SimpleDateFormat sdf_ymd = new SimpleDateFormat("yyyy-MM-dd");

    protected SimpleDateFormat sdf_full = new SimpleDateFormat("yyyy-MM-dd HH:mm");

    @Resource
    protected AttendanceRecordService recordService;

    @Resource
    protected AttendanceRecordMapper recordMapper;

    @Resource
    protected MemberUserService userService;

    @Resource
    protected AttendanceShiftService shiftService;

    @Resource
    protected AttendanceShiftGroupService shiftGroupService;

    @Resource
    protected AttendanceDaySetMapper daySetMapper;

    @Resource
    private DayInfoService dayInfoService;

    /**
     * 判断当前考勤组的时间是否会与现有的考勤计划冲突
     * @param group
     * @return
     */
    protected void check(AttendanceGroup group) {
        // 先检查自己数据(班次)是否会重叠
        List<AttendanceShift> shifts = getAttendanceShifts(group.getAttendanceShiftIds());
        if(!checkShifts(shifts)){
            throw new ServiceException(500,"考勤组内工作时间冲突！");
        }

    }

    /**
     * 获取考勤班次
     * @param attendanceShiftIds
     * @return
     */
    protected List<AttendanceShift> getAttendanceShifts(String attendanceShiftIds) {
        List<AttendanceShiftGroup> groups = shiftGroupService.list(new LambdaQueryWrapper<AttendanceShiftGroup>().eq(AttendanceShiftGroup :: getIsEnable , 0));
        String[] group_arr = new String[groups.size()];
        for(int i = 0 ; i < groups.size() ; i++){
            group_arr[i] = groups.get(i).getId()+"";
        }

        String[] arr = attendanceShiftIds.split(",");
        List<AttendanceShift> shifts = shiftService.list(new LambdaQueryWrapper<AttendanceShift>()
                .in(AttendanceShift::getId , arr)
                .in(AttendanceShift::getAttendanceShiftGroupId , group_arr));

        return shifts;
    }

    /**
     * 获取用户
     * @param orgIds
     * @return
     */
    protected List<MemberUser> getMemberUsers(String orgIds) {
        String[] arr = orgIds.split(",");
        return userService.list(new LambdaQueryWrapper<MemberUser>().in(MemberUser::getOrgId , arr));
    }

    protected boolean checkShifts(List<AttendanceShift> shifts){
        for(AttendanceShift shift : shifts){
            int startTime = Integer.parseInt(shift.getWorkTime().replaceAll(":",""));
            int endTime = Integer.parseInt(shift.getOffWorkTime().replaceAll(":",""));
            endTime = endTime < startTime ? endTime + 2400 : endTime;

            for(AttendanceShift shift_ : shifts){
                if(shift.getId() != shift_.getId()){
                    int startTime_ = Integer.parseInt(shift_.getWorkTime().replaceAll(":",""));
                    int endTime_ = Integer.parseInt(shift_.getOffWorkTime().replaceAll(":",""));
                    endTime_ = endTime_ < startTime_ ? endTime_ + 2400 : endTime_;
                    if((startTime >= startTime_ && startTime <= endTime_ ) || (endTime >= startTime_ && endTime <= endTime_ ) ){
                        return false;
                    }
                }
            }
        }
        return true;
    }

    /**
     * 判断目标日期是否在列表定义的范围内
     * @param day
     * @param daySets
     * @return
     */
    protected boolean isBetween(Date day, List<AttendanceDaySet> daySets) {
        SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMdd");
        Long today = Long.parseLong(sdf.format(day));
        for(AttendanceDaySet set : daySets){
            Long start = Long.parseLong(sdf.format(set.getStartDate()));
            Long end = Long.parseLong(sdf.format(set.getEndDate()));
            if(today>= start && today <=end){
                return true;
            }
        }
        return false;
    }

    /**
     * 检查员工工作时间是否冲突
     * @param user
     * @param record
     * @param records
     */
    protected void checkRepeat(MemberUser user, AttendanceRecord record, List<AttendanceRecord> records) {
        SimpleDateFormat sdf = new SimpleDateFormat("ddHHmm");
        long startTime = Long.parseLong(sdf.format(record.getStartDate()));
        long endTime = Long.parseLong(sdf.format(record.getEndDate()));

        String date = sdf_ymd.format(record.getStartDate());

        for(AttendanceRecord record_ : records){
            if(record.getId() == record_.getId()){
                continue;
            }

            long startTime_ = Long.parseLong(sdf.format(record_.getStartDate()));
            long endTime_ = Long.parseLong(sdf.format(record_.getEndDate()));
            endTime_ = endTime_ < startTime_ ? endTime_ + 2400 : endTime_;
            if((startTime >= startTime_ && startTime <= endTime_ ) || (endTime >= startTime_ && endTime <= endTime_ ) ){
                throw new ServiceException(500,"员工[" + user.getName()+"]在["+date+"]的工作时间冲突！请检查设置");
            }
        }
    }


    protected void doCreatePlan(List<AttendanceRecord> toSave,Date date, AttendanceGroup group, List<MemberUser> users , List<AttendanceShift> shifts){

        String date_str = sdf_ymd.format(date);
        for(AttendanceShift shift : shifts){
            try {
                Date startDate = sdf_full.parse(date_str + " "+ shift.getWorkTime());
                Date endDate = sdf_full.parse(date_str + " "+ shift.getOffWorkTime());
                if(endDate.before(startDate)){// 如果结束时间早于开始时间，需要将结束时间往后+1天
                    Calendar cal = Calendar.getInstance();
                    cal.setTime(endDate);
                    cal.add(Calendar.DATE,1);
                    endDate = cal.getTime();
                }
                for(MemberUser user : users){
                    // 判断是否存在该时间点的考勤计划
                    AttendanceRecord record = recordService.getOne(new LambdaQueryWrapper<AttendanceRecord>()
                            .eq(AttendanceRecord :: getMemberUserId, user.getId())
                            .eq(AttendanceRecord :: getAttendanceGroupId , group.getId())
                            .eq(AttendanceRecord :: getAttendanceShiftId ,shift.getId())
                            .eq(AttendanceRecord :: getStartDate , startDate)
                            .eq(AttendanceRecord :: getEndDate , endDate));

                    if(record == null){
                        record = new AttendanceRecord();
                        record.setMemberUserId(user.getId());
                        record.setAttendanceGroupId(group.getId());
                        record.setAttendanceShiftId(shift.getId());
                        record.setUserName(user.getName());
                        record.setGroupName(group.getGroupName());
                        record.setShiftName(StringUtils.isEmpty(shift.getShiftShortName()) ? shift.getShiftName() : shift.getShiftShortName());
                        record.setStartDate(startDate);
                        record.setEndDate(endDate);
                        record.setIsLate(0);
                        record.setIsLeaveEarly(0);
                        record.setIsAddition(0);
                        record.setIsAbsenceDuty(1);

                        // 获取该用户的已有的考勤计划，判断是否重复
                        AttendanceRecordParam param = new AttendanceRecordParam();
                        param.setMemberUserId(user.getId());
                        param.setStartDate(date_str.replace("-",""));
                        List<AttendanceRecord> records = recordMapper.getRecordsByUserAndDate(param);
                        this.checkRepeat(user,record,records);

                        toSave.add(record);
                    }
                }
            } catch (ParseException e) {
                throw new ServiceException(500,"生成异常，日期转换出错！");
            }
        }
    }

    /**
     * 根据接口请求第二天是否是工作日
     * @param nextDay
     * @return
     */
    protected boolean nextDayIsWorkDay(Date nextDay) {
        String date = sdf_ymd.format(nextDay);
        return dayInfoService.nextDayIsWorkDay(date);
    }




}
